package unittesting;

import static org.junit.Assert.*;

import java.util.*;
import org.junit.Test;

/**
 * Various tests addressing the Java class "StringTokenizer"
 * 
 * @author Stefan Zaruba
 * @version 28.09.2011
 */
public class StringTokenizerTest {

	/**
	 * Instantiates the StringTokenizer with a string of 4 words, separated by blanks.
	 * Afterwards splits up the string at the delimiters and compares them to, previously
	 * defined, expected values, until the Tokenizer does not have any more tokens.
	 * 
	 * @expectations The tokens should match the expected values.
	 */
	@Test
	public void testStringTokenizer() {
		StringTokenizer st = new StringTokenizer("this is a test");
		ArrayList<String> expected = new ArrayList<String>();
		expected.add("this");
		expected.add("is");
		expected.add("a");
		expected.add("test");
		Iterator<String> i = expected.iterator();
		while (st.hasMoreTokens()) {			
			assertEquals(i.next() , st.nextToken());
		}
	}
	
	/**
	 * Invokes the nextToken-method with a delimiter, not occurring in the string.
	 * 
	 * @expectations the whole string should be returned, with the first invocation of nextToken().
	 */
	@Test
	public void testNonOccuringDelimiter() {
		StringTokenizer st = new StringTokenizer("a b c");

		assertEquals("a b c", st.nextToken("&"));
	}
	
	/**
	 * Uses a long delimiter to instantiate the Tokenizer and invoke nextToken().
	 * The delimiter has a two-time repeating sequence of numbers, whilst in the string,
	 * the sequence, between the tokens, repeat one time once and one time twice.
	 * 
	 * @expectations the Tokenizer should identify the single sequence as a delimiter too
	 * and not only the two-time-repeated sequence.
	 */
	@Test
	public void testLongDelimiters(){
		StringTokenizer st = new StringTokenizer("a12341234b1234c", "12341234");

		assertEquals("a", st.nextToken());
		assertEquals("b", st.nextToken());
		assertEquals("c", st.nextToken());
	}
	
	/**
	 * Instantiates the Tokenizer with a null-valued delimiter.
	 * And invokes the nextToken-method given a null-valued delimiter too.
	 * 
	 * @expectations an exception should be thrown as soon as the nextToken-method is invoked for the first time.
	 */
	@Test
	public void testNullDelimiter() {
		StringTokenizer st = new StringTokenizer("a b c", null);
		try{
			st.nextToken();
			fail();
		}catch(NullPointerException e){}
		
		assertEquals("a", st.nextToken(" "));
		
		try{
			st.nextToken(null);
			fail();
		}catch(NullPointerException e){}
	}
	
	/**
	 * Instantiates the Tokenizer with the "delim"-flag set to true, so the nextToken-method will return
	 * the delimiters themselves too.
	 * 
	 * @expectations return the delimiters as tokens too.
	 */
	@Test
	public void testDelimFlag() {
		StringTokenizer st = new StringTokenizer("a.b..c", ".", true);
		assertEquals("a", st.nextToken());
		assertEquals(".", st.nextToken());
		assertEquals("b", st.nextToken());
		assertEquals(".", st.nextToken());
		assertEquals(".", st.nextToken());
		assertEquals("c", st.nextToken());
	}
	
	/**
	 * Instantiates the Tokenizer with an delimiter and later on invokes the nextToken-method with another
	 * delimiter.
	 * 
	 * @expectations the Tokenizer should threat every invocation of nextToken() independently and therefore
	 * only split at the given delimiter.
	 */
	@Test
	public void testVariousDelimiters() {
		StringTokenizer st = new StringTokenizer("a|b|c&d", "|");
		assertEquals("a", st.nextToken());
		assertEquals("b", st.nextToken());
		assertEquals("|c", st.nextToken("&"));
		assertEquals("d", st.nextToken());
	}
	
	/**
	 * Tests whether the nextElement-method returns the right value.
	 * 
	 * @expectations the nextElement-method should return the right value
	 */
	@Test
	public void testNextElement() {
		StringTokenizer st = new StringTokenizer("hi ho hu");
		
		assertEquals("hi", st.nextElement());
		assertEquals("ho", st.nextElement());
		assertEquals("hu", st.nextElement());
	}
	
	/**
	 * Instantiates a Tokenizer with many delimiters in sequence.
	 * 
	 * @expectations more delimiters between tokens should be handled as one.
	 */
	@Test
	public void testMoreDelimitersBetween() {
		StringTokenizer st = new StringTokenizer("   token    haha     	         ok.  ");
		assertTrue(st.countTokens() == 3);

		assertEquals("token",st.nextToken());
		assertEquals("haha",st.nextToken());
		assertEquals("ok.",st.nextToken());
	}
	
	/**
	 * Creates a Tokenizer consisting only of delimiters.
	 * 
	 * @expectations the countTokens-method should return zero.
	 */
	@Test
	public void testDelimitersOnly() {
		StringTokenizer st = new StringTokenizer("       ");
		assertTrue(st.countTokens() == 0);
	}

	/**
	 * Invokes the nextToken-method, though no more tokens are available.
	 * 
	 * @expectations a NoSuchElementException should be thrown.
	 */
	@Test
	public void testNextTokenNotAvailable() {
		StringTokenizer st = new StringTokenizer("test");
		st.nextToken();
		
		try{
			st.nextToken();
			fail();
		}catch(NoSuchElementException e){
			
		}
	}

	/**
	 * Tests whether the countTokens-method returns the right count of tokens
	 * 
	 * @expectations the method should return the right amount of tokens.
	 */
	@Test
	public void testCountTokens() {
		StringTokenizer st = new StringTokenizer("test bla blupp");
		assertTrue(st.countTokens() == 3);
	}

}
